Skip to content

feat: increase text and interactive elems contrast - #2621

Merged
ghostdevv merged 11 commits into
npmx-dev:mainfrom
alexdln:feat/color-contrast
Jul 22, 2026
Merged

feat: increase text and interactive elems contrast#2621
ghostdevv merged 11 commits into
npmx-dev:mainfrom
alexdln:feat/color-contrast

Conversation

@alexdln

@alexdln alexdln commented Apr 24, 2026

Copy link
Copy Markdown
Member

🔗 Linked issue

Resolves #1510

🧭 Context

One of the issues with the a11y and a recurring topic with the community is poor text visibility. I've also experienced this myself. So, I'm trying to increase contrast. As usual, I did it quite carefully - changed the colors by 10% and added a new shade for the borders (I use it for inputs/selects and in the midtone for buttons [I think they need a redesign to make them more visible, not the borders])

I also added foreground shade select so that the user can choose the desired format, where the default contrast is slightly increased from the previous one and we can switch to the old one or to an even higher contrast one

image

@vercel

vercel Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Jul 22, 2026 12:15pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Jul 22, 2026 12:15pm
npmx-lunaria Ignored Ignored Jul 22, 2026 12:15pm

Request Review

@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change adds selectable muted, standard, and contrast foreground themes. It updates theme tokens, persisted settings, prehydration, settings UI, command palette navigation, translations, control styling, and validation coverage.

Changes

Foreground Theme Feature

Layer / File(s) Summary
Design system tokens and theme colours
app/assets/main.css, lunaria/styles.ts, uno.theme.ts, app/components/Button/Base.vue, app/components/Input/Base.vue, app/components/Select/Base.vue, app/components/VersionSelector.vue
Foreground theme variables and elevated border tokens are added for light, dark, and high-contrast modes. Shared controls and the version selector use the updated styling tokens.
Core state management and prehydration
shared/utils/constants.ts, app/composables/useSettings.ts, app/utils/prehydrate.ts
Foreground theme constants, settings fields, defaults, composable state, persistence, root dataset synchronisation, and allowlist validation are added.
Foreground theme picker UI
app/components/Settings/FgThemePicker.vue, app/pages/settings.vue
A swatch-based radio picker is added to the Appearance settings section, including SSR hydration handling and forced-colours styling.
Command palette integration
app/types/command-palette.ts, app/composables/useCommandPaletteGlobalCommands.ts, i18n/locales/en.json, i18n/schema.json
The command palette gains a foreground-themes view, selection commands, navigation, announcements, labels, and matching schema entries.
Foreground theme validation coverage
test/e2e/hydration.spec.ts, test/nuxt/a11y.spec.ts, test/nuxt/components/CommandPalette.spec.ts, test/nuxt/components/HeaderConnectorModal.spec.ts, test/nuxt/composables/use-command-palette-commands.spec.ts
Hydration, accessibility, command palette, settings fixture, and foreground theme command behaviour are tested.

Sequence Diagram(s)

sequenceDiagram
  participant SettingsPage
  participant useForegroundTheme
  participant document.documentElement
  participant localStorage
  SettingsPage->>useForegroundTheme: select foreground theme
  useForegroundTheme->>document.documentElement: set data-fg-theme
  useForegroundTheme->>localStorage: persist preferredForegroundTheme
  localStorage->>document.documentElement: prehydrate saved theme
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: increasing contrast for text and interactive elements.
Description check ✅ Passed The description is clearly about improving contrast and adding a foreground shade selector, which matches the changeset.
Linked Issues check ✅ Passed The PR addresses the issue's contrast goals with border colour updates and a non-default foreground theme selector.
Out of Scope Changes check ✅ Passed The added settings, command-palette, i18n, and test updates support the contrast-theme work and do not appear unrelated.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Apr 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.90476% with 16 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/utils/prehydrate.ts 0.00% 4 Missing and 2 partials ⚠️
app/composables/useCommandPaletteGlobalCommands.ts 66.66% 3 Missing and 2 partials ⚠️
app/composables/useSettings.ts 63.63% 3 Missing and 1 partial ⚠️
app/components/Settings/FgThemePicker.vue 85.71% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented May 13, 2026

Copy link
Copy Markdown

Lunaria Status Overview

🌕 This pull request will trigger status changes.

Learn more

By default, every PR changing files present in the Lunaria configuration's files property will be considered and trigger status changes accordingly.

You can change this by adding one of the keywords present in the ignoreKeywords property in your Lunaria configuration file in the PR's title (ignoring all files) or by including a tracker directive in the merged commit's description.

Tracked Files

File Note
i18n/locales/en.json Source changed, localizations will be marked as outdated.
Warnings reference
Icon Description
🔄️ The source for this localization has been updated since the creation of this pull request, make sure all changes in the source have been applied.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/components/Settings/FgThemePicker.vue`:
- Around line 8-11: The selector construction using
settings.preferredForegroundTheme (variable id) can throw if id contains invalid
characters; update the prehydrate logic in FgThemePicker.vue to validate or
sanitize id before passing it to el.querySelector: either check that id exists
in the canonical list of theme ids used by this component (e.g., the array/prop
that holds available theme ids) and only build the selector when it matches, or
call CSS.escape(id) to safely escape the value before interpolation; ensure you
reference and use the same identifier names (settings.preferredForegroundTheme /
id and the el.querySelector(...) call) when applying the validation/sanitization
so querySelector cannot be given a malformed selector.

In `@app/utils/prehydrate.ts`:
- Around line 42-46: preferredForegroundTheme is read from settings and applied
directly to document.documentElement.dataset.fgTheme; validate it first against
the allowed set ["muted","standard","contrast"] before assigning. Update the
logic around settings.preferredForegroundTheme in prehydrate.ts to: check that
preferredForegroundTheme is a string and is one of the allowed ids (e.g., via a
small const ALLOWED_FG_THEMES = new Set([...]) or array.includes), and only then
set document.documentElement.dataset.fgTheme = preferredForegroundTheme;
otherwise skip the assignment (or fall back to a safe default).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f6954aee-32cc-45e6-ac0c-22c64796aaad

📥 Commits

Reviewing files that changed from the base of the PR and between c2c2754 and c7bab73.

📒 Files selected for processing (21)
  • app/assets/main.css
  • app/components/AppHeader.vue
  • app/components/Button/Base.vue
  • app/components/Input/Base.vue
  • app/components/Select/Base.vue
  • app/components/Settings/FgThemePicker.vue
  • app/composables/useCommandPaletteGlobalCommands.ts
  • app/composables/useSettings.ts
  • app/pages/settings.vue
  • app/types/command-palette.ts
  • app/utils/prehydrate.ts
  • i18n/locales/en.json
  • i18n/schema.json
  • lunaria/styles.ts
  • shared/utils/constants.ts
  • test/e2e/hydration.spec.ts
  • test/nuxt/a11y.spec.ts
  • test/nuxt/components/CommandPalette.spec.ts
  • test/nuxt/components/HeaderConnectorModal.spec.ts
  • test/nuxt/composables/use-command-palette-commands.spec.ts
  • uno.theme.ts

Comment thread app/components/Settings/FgThemePicker.vue
Comment thread app/utils/prehydrate.ts
@trueberryless

Copy link
Copy Markdown
Member

Looks very clean, amazing work 🥰

One nitpicky detail I noticed: The version seems a little bit more grey than all the other text around it. Not sure if this is a11y related, but I think we could change it to be white as well (currently it only gets white on hover).

Screenshot_20260603-151427.png

Wdyt?

@alexdln

alexdln commented Jun 3, 2026

Copy link
Copy Markdown
Member Author

@trueberryless Good point, we've heard many times that the version is too unnoticeable and needs to be more visible

@ghostdevv

Copy link
Copy Markdown
Member

@alexdln we still wanna merge this? If so I can rebase and review 😄

@gameroman gameroman added the front Frontend, Design label Jul 6, 2026
@WilcoSp

WilcoSp commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

at least in my opinion this should be merged eventually as it does improve accessibility.

the only reason why I hadn't reviewed this pr was because of the concerns that coderabbit had raised.

@alexdln

alexdln commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@ghostdevv thank you for the bump, ready for review :)

Comment on lines +76 to +77
test.describe('foreground theme: contrast', () => {
for (const page of PAGES) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also test.for and describe.for

@ghostdevv
ghostdevv added this pull request to the merge queue Jul 22, 2026
Merged via the queue into npmx-dev:main with commit dcd0a76 Jul 22, 2026
23 checks passed
ayo-run pushed a commit to ayo-run/npmx.dev that referenced this pull request Aug 5, 2026
Co-authored-by: Willow (GHOST) <git@willow.sh>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

front Frontend, Design

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Non-text contrast is not sufficient (almost everywhere)

5 participants